package com.eryos.android.cigarettecounter;

/**
 * Project :  CigaretteCounter
 * Author :   Olivier Combe 
 * URL :      http://eryos.fr/CigaretteCounter/
 *
 * Copyright (C) 2011 - Olivier Combe 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 */

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.eryos.android.cigarettecounter.io.DataExporter;
import com.eryos.android.cigarettecounter.io.DataImporter;
import com.eryos.android.cigarettecounter.io.Preferences;
import com.eryos.android.cigarettecounter.io.RestClient;
import com.eryos.android.cigarettecounter.io.RestClient.RequestMethod;
import com.eryos.android.cigarettecounter.tool.GoogleAnalyticsProvider;
import com.eryos.android.cigarettecounter.tool.LogReporterInterface;
import com.eryos.android.cigarettecounter.tool.LogReporterInterface.LogLevel;
import com.eryos.android.cigarettecounter.widget.CigaretteCounterWidger;

public class ConfigActivity extends RootActivity {

	/** *************** UI Elements *************** **/	
	// Data part
	private Button cleanDataButton; 
	private Button exportButton; 
	private Button importButton; 
	
	private CheckBox blankDayCheckBox;

	// Cost part
	private Spinner boxSpinner;
	private ArrayAdapter<CharSequence> adapter;
	private EditText priceInputField;

	// Widget part
	private EditText widgetLowLevelField;
	private EditText widgetHighLevelField;

	private Button validButton; 
	private Button sendLogButton;
	
	// Market Part
	private Button checkUpdateButton; 
	private TextView marketLastVersionField;
	private Button marketUpdateButton; 
	
	/** *************** Instance Variables *************** **/
	private int boxSize = -1;
	private float boxPrice = -1l;
	private float cigPrice = -1l;

	/* Android Market Information */
	private String marketLastVersion;
	private int    marketLastVersionCode;
	private String marketPackageName;
	private String marketID;

	boolean lock = true;
	
	// Need handler for callbacks to the UI thread
	final Handler mHandler = new Handler();

	// Create runnable for posting
	Runnable mCheckUpdateOk = new Runnable() {
		public void run() {
			checkForUpdateComplete();
		}
	};

	Runnable mImportOk = new Runnable() {
		public void run() {
			importDataComplete();
		}
	};

	Runnable mExportOk = new Runnable() {
		public void run() {
			exportDataComplete();
		}
	};

	Runnable mDeleteOk = new Runnable() {
		public void run() {
			deleteDataComplete();
		}
	};

	
	/** ###################################################################### **/
	/** ###################################################################### **/
	
	
	/**
	 * Method used to init values (no UI component, data & default values only)
	 */
	public void initValues(){    	
		marketLastVersionCode = -1;
		marketLastVersion = "NA";
		marketPackageName = null;
		marketID = null;
	}

	/**
	 * Method used to init UI component (no data)
	 */
	public void initUI(){    	
		setContentView(R.layout.config);
		
		// Data
		cleanDataButton 		= (Button) findViewById(R.id.config_data_delete_button);
		exportButton 			= (Button) findViewById(R.id.config_data_export_button);
		importButton 			= (Button) findViewById(R.id.config_data_import_button);

		// Market
		checkUpdateButton		= (Button) findViewById(R.id.config_app_check_update_button);  
		marketLastVersionField	= (TextView) findViewById(R.id.config_app_last_version);
		marketUpdateButton		= (Button) findViewById(R.id.config_app_update_button); 

		// Cost
		boxSpinner 				= (Spinner) findViewById(R.id.config_cost_size_value);
		priceInputField			= (EditText) findViewById(R.id.config_cost_price_value);
		adapter 				= ArrayAdapter.createFromResource( this, R.array.sizes_array, android.R.layout.simple_spinner_item);
		
		// Widget
		widgetLowLevelField		= (EditText) findViewById(R.id.config_level_low_value); 
		widgetHighLevelField	= (EditText) findViewById(R.id.config_level_high_value);
		
		blankDayCheckBox		= (CheckBox)findViewById(R.id.config_data_average_checkbox);
		validButton 			= (Button) findViewById(R.id.config_cost_valid_button);
		sendLogButton  			= (Button) findViewById(R.id.config_app_send_log_button);  
		
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		boxSpinner.setAdapter(adapter);

	}
	
	
	/**
	 * Method called to update UI after data initialization
	 */
	public void updateUI(){
		
		loadConfig();
		
		validButton.requestFocus();
		validButton.bringToFront();
	}

	
	/**
	 * Method use to call a Web Service to check if a new version of the application is available
	 * on official Android Market
	 */
	public void checkForUpdate(){
		
		GoogleAnalyticsProvider.trackEvent("CheckForUpdate", "");
		
		// Retrieve last version deployed on Android Market 
		RestClient client = new RestClient("http://eryos-androidmarketinformation.appspot.com/androidmarketinformation");
		client.addParam("appli", "com.eryos.android.cigarettecounter");

		try {
			// Call WS
			client.execute(RequestMethod.GET);

			// Parse response
			String response = client.getResponse();
			if ( response != null ) {
				String[] responseLines = response.split("\n");
				for ( String line : responseLines){
					String[] elements = line.split(":");
					if ( elements[0] != null && elements.length == 2 && elements[0].equalsIgnoreCase("Version"))
						marketLastVersion = elements[1];
					else if( elements[0] != null && elements.length == 2 && elements[0].equalsIgnoreCase("Package"))
						marketPackageName = elements[1];
					else if( elements[0] != null && elements.length == 2 && elements[0].equalsIgnoreCase("ID"))
						marketID = elements[1];
					else if( elements[0] != null && elements.length == 2 && elements[0].equalsIgnoreCase("VersionCode"))
						marketLastVersionCode = Integer.valueOf(elements[1]);
				}
			}
		}
		catch (UnknownHostException e) {
			// No Connection available
			Toast.makeText(this, "No available connection, please retry later ...", Toast.LENGTH_SHORT).show();
		}
		catch (Exception e) {
			Log.e(getLogTag(), "initValues(Market)", e);
		}
	}

	/**
	 * Called when 'Check For Update' action is complete
	 */
	public void checkForUpdateComplete(){
		/* Refresh informations from Android Market */
		marketLastVersionField.setText(marketLastVersion);
		if (marketID != null ){
			try {
				PackageInfo packageInfo = this.getPackageManager().getPackageInfo(this.getPackageName(), 0);                           
				int currentVersionCode = packageInfo.versionCode;

				if( currentVersionCode < marketLastVersionCode )				
					marketUpdateButton.setEnabled(true);

			} catch (NameNotFoundException e) {
				Log.e(getLogTag(), "updateUI - VersionCode", e);
			}
		}
		
		hideWaitingMessage();
	}
	
	/**
	 * Used to retrieve params already defined
	 */
	public void loadConfig(){
		Log.i(getLogTag(), "Load Config");

		Preferences pref = new Preferences(getSharedPreferences(PREFS_NAME, 0));
		pref.readParamFromFile();
		
		// Cost Part
		boxPrice = pref.getBoxPrice();
		boxSize = pref.getBoxSize();
		lock = pref.getLock();

		int position = 0;
		position = adapter.getPosition(String.valueOf(boxSize));

		if ( boxPrice != -1l )
			priceInputField.setText(boxPrice+"");

		if ( boxSize != -1 && boxSpinner != null ){
			boxSpinner.setSelection(position);
		}
		Log.d(getLogTag(), "[updateUI] Size : "+boxSize+" Position : "+position);
		
		int lowValue = pref.getMediumUsageLow();
		int highValue = pref.getMediumUsageHigh();

		Log.d(getLogTag(), "[updateUI] Low : "+lowValue+" High : "+highValue);
		
		// Widget Part
		widgetLowLevelField.setText(String.valueOf(lowValue));
		widgetHighLevelField.setText(String.valueOf(highValue));
		
	}
	
	/**
	 * Save the current params values
	 */
	public void saveConfig(){
		Log.i(getLogTag(), "Save Config");

		Preferences pref = new Preferences(getSharedPreferences(PREFS_NAME, 0));

		// Cost Param
		try {
			// Retrieve Cost params
			pref.setBoxSize(boxSize);
			Float boxPrice = new Float(priceInputField.getText().toString());
			pref.setBoxPrice(boxPrice);
			cigPrice = boxPrice / boxSize;
			pref.setCigarettePrice(cigPrice);
			Log.d(getLogTag(), "[saveConfig] Save Config Price : "+boxPrice+" Size : "+boxSize+"Cigarette Price: "+cigPrice);

			// Store param
			pref.storeParamToFile();

		} catch (Exception e) {
			Log.w(getLogTag(), "Save Config", e);
		}
		
		// Widget Param
		try {

			// Retrieve Widget params
			pref.setMediumUsageLow(Integer.valueOf(widgetLowLevelField.getText().toString()));
			pref.setMediumUsageHigh(Integer.valueOf(widgetHighLevelField.getText().toString()));
			
			Log.d(getLogTag(), "[saveConfig] Low "+widgetLowLevelField.getText().toString()+" High : "+widgetHighLevelField.getText().toString());
			
	    	// Update widget(s)
	    	CigaretteCounterWidger.updateAllWidgets(this.getApplicationContext());

			// Store param
			pref.storeParamToFile();

		} catch (Exception e) {
			Log.w(getLogTag(), "Save Config", e);
		}

		hideWaitingMessage(R.string.config_valid_OK);
	}

	/**
	 * Delete all data from DB
	 */
	public void deleteData(){
		Log.i(getLogTag(), "Delete All Data");
		db.deleteAll();
	}

	/**
	 * Called when 'Delete Data' action is completed
	 */
	public void deleteDataComplete(){
		hideWaitingMessage(R.string.config_delete_OK);
	}

	/**
	 * Export data to SD card ( Public Downloads folder )
	 */
	public void exportData(){
		Log.i(getLogTag(), "Export data to SD");
		GoogleAnalyticsProvider.trackEvent("ExportToSD", "");
		
		// Open Stream
		DataExporter export = new DataExporter(SDCARD_NAME);
		int nbExport = 0;

		try {
			if ( export.openStream() ){

				// Retrieve data from DB
				List<String> data = db.exportData();
				nbExport = data.size();
				nbExport--;

				// Write data to file (line by line)
				for (String line : data )
					export.writeDataToExternalFile(line+"\n");

				// Close Stream
				export.closeStream();
			}
		} catch (IOException e) {
			Log.e(getLogTag(), "Export data to SD", e);
			hideWaitingMessage(getResources().getString(R.string.config_export_NOK, SDCARD_NAME));
		}    	
	}

	/**
	 * Called whe 'Export Data' action is completed
	 */
	public void exportDataComplete(){
		hideWaitingMessage(getResources().getString(R.string.config_export_OK, SDCARD_NAME));
	}

	/**
	 * Import data from SD Card file
	 */
	public void importData(){
		Log.i(getLogTag(), "Import data from SD");
		GoogleAnalyticsProvider.trackEvent("ImportFromSD", "");
		
		// Open Stream
		DataImporter importer = new DataImporter(SDCARD_NAME);
		int nbImport = 0;
		try {
			
			// Check is stream is OK
			if ( importer.openStream() ){

				// Read data from file
				ArrayList<String> data = importer.readDataFromExternalFile();
				
				// Insert data into DB 
				nbImport = db.importData(data);

				// Close Stream
				importer.closeStream();
			}
		} catch (IOException e) {
			Log.e(getLogTag(), "importData", e);
			hideWaitingMessage(getResources().getString(R.string.config_import_NOK, SDCARD_NAME));
		}
	}

	/**
	 * Called when 'Import Data' action is completed
	 */
	public void importDataComplete(){
		hideWaitingMessage(getResources().getString(R.string.config_import_OK, SDCARD_NAME));
	}

	
	/** ###################################################################### **/
	/** ###################################################################### **/

	
	/**
	 * Method used to define all handlers (button, spinner, mouse, etc.)
	 */
	public void initHandlers() {

		boxSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { 
				String res = parent.getItemAtPosition(pos).toString(); 
				boxSize = Integer.valueOf(res);
			} 

			public void onNothingSelected(AdapterView<?> parent) { } 
		});            

		validButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showWaitingMessage();
				saveConfig();
			}
		});

		cleanDataButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showWaitingMessage();            	
				Thread t = new Thread() {
					public void run() {
						// Process action
						deleteData();
						
						// Action complete, send message to end user
						mHandler.post(mDeleteOk);
					}
				};
				t.start();
			}
		});

		exportButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showWaitingMessage();
				Thread t = new Thread() {
					public void run() {
						// Process action
						exportData();
						
						// Action complete, send message to end user
						mHandler.post(mExportOk);
					}
				};
				t.start();
			}
		});

		importButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showWaitingMessage();
				Thread t = new Thread() {
					public void run() {
						// Process action
						importData();
						
						// Action complete, send message to end user
						mHandler.post(mImportOk);
					}
				};
				t.start();
			}
		});

		marketUpdateButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// Link to Market : 
				String uri = "http://market.android.com/details?id=" + marketPackageName; 
				Log.d(getLogTag(), "uri: " + uri); 
				Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); 
				ConfigActivity.this.startActivity(intent); 
			}
		});	  

		checkUpdateButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showWaitingMessage();
				Thread t = new Thread() {
					public void run() {
						// Process action
						checkForUpdate();
						
						// Action complete, send message to end user
						mHandler.post(mCheckUpdateOk);
					}
				};
				t.start();
			}
		});	  

		sendLogButton.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showWaitingMessage();

				extractLog();

				hideWaitingMessage();
			}
		}); 
	}
	
	/**
	 * Send log to dev team (// TODO )
	 */
	public void extractLog(){

		GoogleAnalyticsProvider.trackEvent("Debug", "SendLog");
		
		LogReporterInterface logReporter = new LogReporterInterface(ConfigActivity.this);		

		/* Mail config */
		
		logReporter.addMailRecipient(getResources().getString(R.string.config_log_mail_recipient));
		logReporter.setMailSubject(getResources().getString(R.string.config_log_mail_subject));
		logReporter.setMailMessage("Please find Log file in attachment \n\n <Your message here> \n\n");

		/* Log Config */
		logReporter.setDebugInfo("App Version :"+ getString(R.string.version)+"\n"+"Build :"+ getString(R.string.build));		
		logReporter.setMaxLogLines(1500);

		/* Log Filters */
		logReporter.addLogFilter("CigaretteCounter", LogLevel.ALL);
		logReporter.addLogFilter("CigaretteDatabase", LogLevel.ALL);
		logReporter.addLogFilter("ConfigActivity", LogLevel.ALL);
		logReporter.addLogFilter("HistoryActivity", LogLevel.ALL);
		logReporter.addLogFilter("CigaretteWidget", LogLevel.ALL);
		logReporter.addLogFilter("ActivityManager", LogLevel.ALL);

		/* Extract data from logs */
		logReporter.start();
	}
}
